/* uuid32.c 
2007-09-15 Last created by cheungmine.
Partly rights reserved by cheungmine.
*/

#include <stdio.h>
#include <time.h>
#include <sys/types.h>
#include <sys/timeb.h>
#include <objbase.h>

#include "uuid32.h"
#include "cdatatype.h"

#define UUID_LEN	36
using namespace std;
/*========================================================================================
Private Functions
========================================================================================*/
static bool isbigendian()
{
	int c = 1;
	return ( *((unsigned char *) &c) == 1 )? false: true;
};

static void swap_word( int size_bytes, void * ptr_word )
{
	int	i;
	unsigned char	temp;
	for( i=0; i < size_bytes/2; i++ )
	{
	temp = ((unsigned char *) ptr_word)[i];
	((unsigned char *) ptr_word)[i] = ((unsigned char *) ptr_word)[size_bytes-i-1];
	((unsigned char *) ptr_word)[size_bytes-i-1] = temp;
	}
};

static void write_word( unsigned char* stream, word_t val )
{
	memcpy(stream, &val, 2);
	if( isbigendian()) 
	swap_word(2,stream);
};

static void write_dword( unsigned char* stream, dword_t val )
{
	memcpy(stream, &val, 4);
	if( isbigendian()) 
	swap_word(4,stream);
};

static void	read_word( const unsigned char* stream, word_t* val )
{
	memcpy( val, stream, 2 );
	if( isbigendian() )	
	swap_word( 2, val );
};

static void	read_dword( const unsigned char* stream, dword_t* val )
{
	memcpy( val, stream, 4 );
	if(isbigendian())    
	swap_word( 4, val );
};

/**
* internal
* ingroup uuid
* The thread synchronization lock used to guarantee UUID uniqueness
* for all the threads running within a process.
*/
void uuid_create(uuid* uid) 
{    
#ifdef _WIN32
	CoCreateGuid(uid);
#else
	uuid_generate(*uid);
#endif
}

/**
* internal
* ingroup uuid
* The thread synchronization lock used to guarantee UUID uniqueness
* for all the threads running within a process.
*/
string uuid_create_string(void) 
{
	uuid  uid;
	uuid_create(&uid);
	return uuid_to_string(&uid);
}

string uuid_to_string(const uuid*  u)
{
	char uuid_str[UUID_LEN+1];

#ifdef _WIN32
	ushort a,b;
	uint32  c;
	read_word(&(u->Data4[6]), &a);
	read_word(&(u->Data4[4]), &b);
	read_dword(&(u->Data4[0]), &c);

	#pragma warning(push)    /* C4996 */
	#pragma warning( disable : 4996 )
	sprintf(uuid_str,"%08lx-%04x-%04x-%04x-%04x%08lx", 
						u->Data1,
						u->Data2,
						u->Data3,
						a, b, c);
	#pragma warning(pop)    /* C4996 */
#else
	const unsigned char* puuid = &(*u)[0];
	uint32 data1,data4c;
	ushort data2,data3,data4a,data4b;
	read_dword(puuid,&data1);
	puuid+= SIZE_DWORD;
	read_word(puuid,&data2);
	puuid+= SIZE_SHORT;
	read_word(puuid,&data3);
	puuid+= SIZE_SHORT;
	read_word(puuid,&data4a);
	puuid+= SIZE_SHORT;
	read_word(puuid,&data4b);
	puuid+= SIZE_SHORT;
	read_dword(puuid,&data4c);

	sprintf(uuid_str,"%08lx-%04x-%04x-%04x-%04x%08lx", 
							data1,data2,data3,
							data4a, data4b, data4c);
#endif

	return string(uuid_str);
}

